package com.chenfan.process.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenfan.infra.context.UserContextHolder;
import com.chenfan.infra.vo.UserVO;
import com.chenfan.process.common.constants.CommonFieldConstants;
import com.chenfan.process.common.utils.QueryWrapperUtils;
import com.chenfan.process.entity.po.ProcessInstanceApprovePo;
import com.chenfan.process.entity.po.TemplateConfigPo;
import com.chenfan.process.enums.BooleanEnum;
import com.chenfan.process.enums.InstanceEnums;
import com.chenfan.process.enums.StatusEnums;
import com.chenfan.process.repository.ProcessInstanceApproveRepository;
import com.chenfan.process.service.ProcessInstanceApproveService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author K
 * @date 2021-04-26
 */
@Service
public class ProcessInstanceApproveServiceImpl extends
    ServiceImpl<ProcessInstanceApproveRepository, ProcessInstanceApprovePo> implements ProcessInstanceApproveService {

    @Override
    public void updateApproval(Long approvalId, Integer status) {
        UserVO userVo = UserContextHolder.getUserVo();
        UpdateWrapper<ProcessInstanceApprovePo> updateWrapper = new UpdateWrapper<>();

        if (Objects.nonNull(userVo)) {
            updateWrapper.set(CommonFieldConstants.UPDATE_NAME, userVo.getRealName());
            updateWrapper.set(CommonFieldConstants.UPDATE_BY, userVo.getUserId());
        }
        updateWrapper.set(CommonFieldConstants.STATUS, status);
        updateWrapper.set(CommonFieldConstants.UPDATE_TIME, new Date());
        updateWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        updateWrapper.eq(CommonFieldConstants.STATUS, BooleanEnum.N.getCode());
        this.update(updateWrapper);
    }

    @Override
    public void updateApproval(Long approvalId, Integer status, String remark) {
        UserVO userVo = UserContextHolder.getUserVo();
        UpdateWrapper<ProcessInstanceApprovePo> updateWrapper = new UpdateWrapper<>();

        if (Objects.nonNull(userVo)) {
            updateWrapper.set(CommonFieldConstants.UPDATE_NAME, userVo.getRealName());
            updateWrapper.set(CommonFieldConstants.UPDATE_BY, userVo.getUserId());
        }
        updateWrapper.set(CommonFieldConstants.STATUS, status);
        updateWrapper.set(!StringUtils.isEmpty(remark), ProcessInstanceApprovePo.REMARK, remark);
        updateWrapper.set(CommonFieldConstants.UPDATE_TIME, new Date());
        updateWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        updateWrapper.eq(CommonFieldConstants.STATUS, BooleanEnum.N.getCode());
        this.update(updateWrapper);
    }

    @Override
    public void updateApprovalAlone(Long approvalId, Integer status, String remark, Long userId, TemplateConfigPo config) {
        List<ProcessInstanceApprovePo> approval = getApproval(approvalId);
        // 过滤出自身数据
        UserVO userVo = UserContextHolder.getUserVo();
        if (Objects.nonNull(userVo)) {
            approval.forEach(e -> {
                if (Objects.equals(e.getUserId(), userVo.getUserId())) {
                    e.setStatus(status);
                    e.setRemark(remark);
                    e.updateSelf();
                } else {
                    if ((Objects.nonNull(config) && config.historySkip()) || Objects.equals(e.getUserId(), userId)) {
                        e.setStatus(status);
                        e.setRemark(remark);
                        e.updateSelf();
                        e.setUpdateName(e.getUserName());
                        e.setUpdateBy(e.getUserId());
                    } else {
                        // 删除多余的数据
                        e.setDeletedFlag(Boolean.TRUE);
                    }
                }
            });
            this.updateBatchById(approval);
            return;
        }
        updateApproval(approvalId, status, remark);
    }

    @Override
    public void updateApproval(Long approvalId, Integer status, Long userId, String userName) {
        UpdateWrapper<ProcessInstanceApprovePo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(CommonFieldConstants.STATUS, status);
        updateWrapper.set(CommonFieldConstants.UPDATE_TIME, new Date());
        updateWrapper.set(CommonFieldConstants.UPDATE_NAME, userName);
        updateWrapper.set(CommonFieldConstants.UPDATE_BY, userId);
        updateWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        updateWrapper.eq(CommonFieldConstants.STATUS, BooleanEnum.N.getCode());
        this.update(updateWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> getApproval(Long approvalId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        queryWrapper.eq(ProcessInstanceApprovePo.STATUS, StatusEnums.NORMAL.getCode());
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> getApprovalWithoutStatus(Long approvalId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        queryWrapper.isNotNull(ProcessInstanceApprovePo.STATUS);
        return this.list(queryWrapper);
    }

    @Override
    public ProcessInstanceApprovePo getByApprovalId(Long approvalId) {
        List<ProcessInstanceApprovePo> approval = getApproval(approvalId);
        return CollectionUtils.isEmpty(approval) ? null : approval.get(0);
    }

    @Override
    public List<ProcessInstanceApprovePo> getByDetailId(Long approvalId, Long detailId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_DETAIL_ID, detailId);
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> getByDetailIdWithoutStatus(Long approvalId, Long detailId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_DETAIL_ID, detailId);
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> getByDetailAndId(Long approvalId, Long detailId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_ID, approvalId);
        queryWrapper.eq(ProcessInstanceApprovePo.STATUS, InstanceEnums.NORMAL.getCode());
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_DETAIL_ID, detailId);
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> listByDetailIdList(List<Long> detailIdList) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.in(ProcessInstanceApprovePo.APPROVAL_DETAIL_ID, detailIdList);
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> listApprovingInstance(Long approvalTemplateId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.eq(ProcessInstanceApprovePo.STATUS, InstanceEnums.NORMAL.getCode());
        queryWrapper.eq(ProcessInstanceApprovePo.APPROVAL_TEMPLATE_ID, approvalTemplateId);
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> listApprovingInstances(Collection<Long> approvalIdList, Integer status) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.in(ProcessInstanceApprovePo.APPROVAL_ID, approvalIdList);
        queryWrapper.eq(Objects.nonNull(status), ProcessInstanceApprovePo.STATUS, status);
        return this.list(queryWrapper);
    }

    @Override
    public List<ProcessInstanceApprovePo> listApprovingInstance(List<Long> approvalTemplateId) {
        QueryWrapper<ProcessInstanceApprovePo> queryWrapper = QueryWrapperUtils.newQueryWrapper();
        queryWrapper.eq(ProcessInstanceApprovePo.STATUS, InstanceEnums.NORMAL.getCode());
        queryWrapper.in(ProcessInstanceApprovePo.APPROVAL_TEMPLATE_ID, approvalTemplateId);
        return this.list(queryWrapper);
    }
}
